#ifndef LIBVP_HPP
#define LIBVP_HPP

#include <cstring>
#include <fstream>
#include <sstream> // for getNameWithCount()
#include <string>
#include <vector>

#ifdef WIN32
#define strcasecmp _stricmp
#endif

class TreeEntry
{
public:
  TreeEntry(){};
  TreeEntry(int inoffset, int insize, std::string inname, int intimestamp)
  {
    offset = inoffset;
    size = insize;
    name = inname;
    timestamp = intimestamp;
  };
  bool isBackDir() {return (isDir() && (name == ".."));};
  bool isDir() {return ((size == 0) && (timestamp == 0));};
  bool isFile() {return (!isDir());};

  int getOffset() {return offset;};
  int getSize() {return size;};
  std::string getName() {return name;};
  int getTimestamp() {return timestamp;};
private:
  std::string name;
  int offset, size, timestamp;
};

class VPFile
{
public:
  VPFile();
  VPFile(TreeEntry inElement)
  {
    offset = inElement.getOffset();
    size = inElement.getSize();
    name = inElement.getName();
    timestamp = inElement.getTimestamp();
  };

  int getOffset() {return offset;};
  int getSize() {return size;};
  std::string getSizeStr();
  std::string getName() {return name;};
  int getTimestamp() {return timestamp;};
private:
  std::string name;
  int offset, size, timestamp;
};

class VPDir
{
public:
  VPDir(){};
  VPDir(TreeEntry inelement){fromEntry(inelement);};

  void fromEntry(TreeEntry inelement) {name = inelement.getName();};
  void addSubdir(VPDir insub) {subdirs.push_back(insub);};
  void addFile(VPFile infile) {files.push_back(infile);};
  // TODO: Add iterators?
  std::vector <VPDir> getSubdirs() {return subdirs;};
  std::vector <VPFile> getFiles() {return files;};

  std::string getName() {return name;};
  std::string getNameWithCount();
private:
  std::string name;
  std::vector <VPDir> subdirs;
  std::vector <VPFile> files;
};

class VP
{
public:
  VP(){};
  VP(std::string infilepath);
  VPDir getDataDir() {return datadir;};
  ~VP() {inFile.close();};

  void open(std::string infilepath);
  void close();
  std::vector<char> exportFile(VPFile in_storethis);

  static bool compareElements(VPDir a, VPDir b)
  {return (a.getName() < b.getName());};
  static bool compareElements(VPFile a, VPFile b)
  {return (a.getName() < b.getName());};

private:
  void parseChildren(VPDir* dir);
  TreeEntry parseElement();

  std::ifstream inFile;
  int diroffset;
  int direntries;
  VPDir datadir;
};

#endif //LIBVP_HPP
